"""
KidsBuddy 1.0 验证工具
提供数据验证和类型检查功能
"""

import re
from typing import Any, Dict, List, Optional, Union, TypeVar, Generic, Callable


T = TypeVar('T')


class ValidationError(Exception):
    """验证错误异常"""

    def __init__(self, message: str, field: Optional[str] = None):
        self.message = message
        self.field = field
        super().__init__(f"{field + ': ' if field else ''}{message}")


class Validator(Generic[T]):
    """通用验证器基类"""

    def __init__(self, error_message: Optional[str] = None):
        self.error_message = error_message

    def validate(self, value: Any) -> T:
        """
        验证值并返回处理后的结果

        Args:
            value: 要验证的值

        Returns:
            验证和处理后的值

        Raises:
            ValidationError: 验证失败时抛出
        """
        raise NotImplementedError("子类必须实现validate方法")


class NotEmptyValidator(Validator[str]):
    """非空字符串验证器"""

    def validate(self, value: Any) -> str:
        if not isinstance(value, str):
            raise ValidationError(self.error_message or "必须是字符串类型")

        if not value.strip():
            raise ValidationError(self.error_message or "不能为空")

        return value.strip()


class RangeValidator(Validator[float]):
    """数值范围验证器"""

    def __init__(self, min_value: Optional[float] = None, max_value: Optional[float] = None,
                 error_message: Optional[str] = None):
        super().__init__(error_message)
        self.min_value = min_value
        self.max_value = max_value

    def validate(self, value: Any) -> float:
        try:
            num_value = float(value)
        except (ValueError, TypeError):
            raise ValidationError(self.error_message or "必须是数值类型")

        if self.min_value is not None and num_value < self.min_value:
            raise ValidationError(
                self.error_message or f"不能小于 {self.min_value}"
            )

        if self.max_value is not None and num_value > self.max_value:
            raise ValidationError(
                self.error_message or f"不能大于 {self.max_value}"
            )

        return num_value


class RegexValidator(Validator[str]):
    """正则表达式验证器"""

    def __init__(self, pattern: str, error_message: Optional[str] = None):
        super().__init__(error_message)
        self.pattern = re.compile(pattern)

    def validate(self, value: Any) -> str:
        if not isinstance(value, str):
            raise ValidationError(self.error_message or "必须是字符串类型")

        if not self.pattern.match(value):
            raise ValidationError(
                self.error_message or "格式不符合要求"
            )

        return value


class SchemaValidator(Validator[Dict[str, Any]]):
    """数据结构验证器"""

    def __init__(self, schema: Dict[str, Dict[str, Any]]):
        """
        初始化结构验证器

        Args:
            schema: 验证架构，格式为 {"字段名": {"validator": 验证器实例, "required": 是否必须}}
        """
        super().__init__()
        self.schema = schema

    def validate(self, data: Any) -> Dict[str, Any]:
        if not isinstance(data, dict):
            raise ValidationError("必须是字典类型")

        validated_data = {}
        errors = []

        for field_name, field_config in self.schema.items():
            validator = field_config.get("validator")
            required = field_config.get("required", True)

            if field_name in data:
                try:
                    validated_data[field_name] = validator.validate(
                        data[field_name])
                except ValidationError as e:
                    errors.append(ValidationError(e.message, field_name))
            elif required:
                errors.append(ValidationError("此字段是必需的", field_name))

        if errors:
            # 构建完整错误消息
            error_messages = [f"{e.field}: {e.message}" for e in errors]
            raise ValidationError(f"验证失败: {', '.join(error_messages)}")

        return validated_data


def validate_email(email: str) -> bool:
    """
    验证电子邮件地址格式

    Args:
        email: 电子邮件地址

    Returns:
        是否为有效的电子邮件地址
    """
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))


def validate_student_id(student_id: str) -> bool:
    """
    验证学生ID格式

    Args:
        student_id: 学生ID

    Returns:
        是否为有效的学生ID
    """
    # 例如，要求学生ID为字母数字组合，长度至少为3
    pattern = r'^[a-zA-Z0-9_]{3,}$'
    return bool(re.match(pattern, student_id))


def validate_session_id(session_id: str) -> bool:
    """
    验证会话ID格式

    Args:
        session_id: 会话ID

    Returns:
        是否为有效的会话ID
    """
    # 会话ID通常包含前缀、时间戳和唯一标识
    pattern = r'^session_[a-zA-Z0-9_]+_\d+$'
    return bool(re.match(pattern, session_id))
